﻿using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace RayD.Core
{
    /// <summary>
    /// IServiceCollection 容器的拓展类
    /// </summary>
    public static partial class Extention
    {
        /// <summary>
        /// 程序集依赖注入
        /// </summary>
        /// <param name="services"></param>
        /// <param name="assemblyName"></param>
        /// <param name="serviceLifetime"></param>
        public static IServiceCollection AddAssembly(this IServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped, params string[] assemblyName)
        {
            if (services == null)
                throw new ArgumentNullException(nameof(services) + "为空");

            if (assemblyName == null || assemblyName.Length < 1)
                throw new ArgumentNullException("程序集为空");

            IEnumerable<Type> types = new List<Type>();

            foreach (var item in assemblyName)
            {
                if (string.IsNullOrEmpty(item))
                    throw new ArgumentNullException(nameof(item) + "为空");

                var assembly = RuntimeHelper.GetAssemblyByName(item);

                if (assembly == null)
                    throw new DllNotFoundException(nameof(assembly) + ".dll不存在");

                types = types.Concat(assembly.GetTypes().AsEnumerable());
            }

            var list = types.Where(o => o.IsClass && !o.IsAbstract && !o.IsGenericType).ToList();
            if (list == null && !list.Any())
                return services;
            foreach (var type in list)
            {
                var interfacesList = type.GetInterfaces();
                if (interfacesList == null || !interfacesList.Any())
                    continue;
                var inter = interfacesList.First();
                switch (serviceLifetime)
                {
                    case ServiceLifetime.Scoped:
                        services.AddScoped(inter, type);
                        break;
                    case ServiceLifetime.Singleton:
                        services.AddScoped(inter, type);
                        break;
                    case ServiceLifetime.Transient:
                        services.AddTransient(inter, type);
                        break;
                }
            }

            return services;
        }
    }
}
